package com.qfhd.soft.cjzcore.Core;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class CJHttp {
    private static CJHttp http = null;
    private static final int BUFFER_SIZE = (1024 * 16);

    public static CJHttp getInstance() {
        if (http == null) {
            synchronized (CJHttp.class) {
                if (http == null) {
                    http = new CJHttp();
                }
            }
        }
        return http;
    }

    private volatile String mUserAgent = null;
    private volatile int mConnectTimeout = 10;
    private volatile int mWriteTimeout = 10;
    private volatile int mReadTimeout = 10;

    private CJHttp() {
        SetUserAgent();
    }

    public void SetUserAgent(String userAgent) {
        if (TextUtils.isEmpty(userAgent))
            SetUserAgent();
        else
            mUserAgent = userAgent;
    }

    private void SetUserAgent() {
        String userAgent = System.getProperty("http.agent");
        StringBuilder sb = new StringBuilder();
        for (int i = 0, length = userAgent.length(); i < length; i++) {
            char c = userAgent.charAt(i);
            if (c <= '\u001f' || c >= '\u007f') {
                sb.append(String.format("\\u%04x", (int) c));
            } else {
                sb.append(c);
            }
        }
        mUserAgent = sb.toString();
    }

    public void setConnectTimeout(int timeout) {
        mConnectTimeout = timeout;
    }

    public void setWriteTimeout(int timeout) {
        mWriteTimeout = timeout;
    }

    public void setReadTimeout(int timeout) {
        mReadTimeout = timeout;
    }

    public void get(String url, CJHttpListener listener) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();
            Request request = new Request.Builder()
                    .url(url)
                    .header("User-Agent", mUserAgent)
                    .build();
            Call getCall = client.newCall(request);
            getCall.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    if (listener != null) {
                        listener.onFailure("error:" + e.toString());
                    }
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (listener != null) {
                        if (response.code() == 200) {
                            listener.onResponse(response.body().string());
                        }
                    }
                }
            });
        } catch (Exception e) {
            CJLogger.e("http get error:" + e.toString());
        }
    }

    public String get(String url) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();
            Request request = new Request.Builder()
                    .url(url)
                    .header("User-Agent", mUserAgent)
                    .build();
            Response response = client.newCall(request).execute();
            return response.body().string();
        } catch (Exception e) {
            CJLogger.e("http get error:" + e.toString());
        }
        return "";
    }

    public String get(String url, String key, String token) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();
            Request request = new Request.Builder()
                    .url(url)
                    .header("User-Agent", mUserAgent)
                    .addHeader(key, token)
                    .build();
            Response response = client.newCall(request).execute();
            return response.body().string();
        } catch (Exception e) {
            CJLogger.e("http get error:" + e.toString());
        }
        return "";
    }

    public void post(String host, Map<String, String> dataMap, CJHttpListener listener) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();
            FormBody.Builder formBodyBuiler = new FormBody.Builder();
            if (dataMap != null) {
                if (dataMap.size() > 0) {
                    for (String key : dataMap.keySet()) {
                        formBodyBuiler.add(key, dataMap.get(key));
                    }
                }
            }
            FormBody formBody = formBodyBuiler.build();
            Request request = new Request.Builder()
                    .url(host)
                    .post(formBody)
                    .header("User-Agent", mUserAgent)
                    .build();
            Call getCall = client.newCall(request);

            getCall.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    if (listener != null) {
                        listener.onFailure("error:" + e.toString());
                    }
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (listener != null) {
                        if (response.code() == 200) {
                            listener.onResponse(response.body().string());
                        }
                    }
                }
            });
        } catch (Exception e) {
            CJLogger.e("http post error:" + e.toString());
        }
    }

    public String post(String host, String jsonData) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();

            RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonData);
            Request request = new Request.Builder()
                    .url(host)
                    .post(requestBody)
                    .header("User-Agent", mUserAgent)
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                CJLogger.e("http post error code:" + response.code() + ", message:" + response.message());
            }
        } catch (Exception e) {
            CJLogger.e("http post error:" + e.toString());
        }
        return "";
    }

    public String post_uploadImg(String host, List<String> fileList,MultipartBody.Builder builder) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout * 10, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout * 10, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout * 10, TimeUnit.SECONDS)
                    .build();
//            MultipartBody.Builder builder = new MultipartBody.Builder();
//            builder.setType(MultipartBody.FORM);
//            builder.addFormDataPart("data", jsonData);
            if (fileList.size() > 0) {
                for (String path : fileList) {
                    String fileName = path;
                    File file = new File(fileName);
                    CJLogger.d(fileName);
                    builder.addFormDataPart("image", file.getName(), RequestBody.create(MediaType.parse("image/jpeg"), file));
                }
            }

            CJLogger.d(builder.build().contentType().toString());
            CJLogger.d(builder.build().type().toString());

            Request request = new Request.Builder()
                    .url(host)
                    .post(builder.build())
                    .header("User-Agent", mUserAgent)
//                    .addHeader(key, token)
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                CJLogger.e("post_upload error code:" + response.code() + ", message:" + response.message());
            }
        } catch (Exception e) {
            CJLogger.e("post_upload error:" + e.toString());
        }
        return "";
    }

    public String post(String host, String jsonData, String key, String token) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();

            RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), jsonData);
            Request request = new Request.Builder()
                    .url(host)
                    .post(requestBody)
                    .header("User-Agent", mUserAgent)
                    .addHeader(key, token)
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                CJLogger.e("http post error code:" + response.code() + ", message:" + response.message());
            }
        } catch (Exception e) {
            CJLogger.e("http post error:" + e.toString());
        }
        return "";
    }

    public String post(String host, Map<String, String> dataMap) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();

            FormBody.Builder formBodyBuiler = new FormBody.Builder();
            if (dataMap != null) {
                if (dataMap.size() > 0) {
                    for (String key : dataMap.keySet()) {
                        formBodyBuiler.add(key, dataMap.get(key));
                    }
                }
            }
            FormBody formBody = formBodyBuiler.build();
            Request request = new Request.Builder()
                    .url(host)
                    .post(formBody)
                    .header("User-Agent", mUserAgent)
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                CJLogger.e("http post error code:" + response.code() + ", message:" + response.message());
            }
        } catch (Exception e) {
            CJLogger.e("http post error:" + e.toString());
        }
        return "";
    }

    public String post(String host, Map<String, String> dataMap, String tokenKey, String token) {
        try {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(mConnectTimeout, TimeUnit.SECONDS)
                    .writeTimeout(mWriteTimeout, TimeUnit.SECONDS)
                    .readTimeout(mReadTimeout, TimeUnit.SECONDS)
                    .build();

            FormBody.Builder formBodyBuiler = new FormBody.Builder();
            if (dataMap != null) {
                if (dataMap.size() > 0) {
                    for (String key : dataMap.keySet()) {
                        formBodyBuiler.add(key, dataMap.get(key));
                    }
                }
            }
            FormBody formBody = formBodyBuiler.build();
            Request request = new Request.Builder()
                    .url(host)
                    .post(formBody)
                    .header("User-Agent", mUserAgent)
                    .addHeader(tokenKey, token)
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                CJLogger.e("http post error code:" + response.code() + ", message:" + response.message());
            }
        } catch (Exception e) {
            CJLogger.e("http post error:" + e.toString());
        }
        return "";
    }

    public boolean quickDownload(String url, String savePath, boolean isOverwrite) {
        File file = new File(savePath);
        boolean flag = false;
        do {
            if (file.exists()) {
                if (isOverwrite) {
                    file.delete();
                } else {
                    flag = true;
                    break;
                }
            }
            try {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder().url(url).build();
                Response response = client.newCall(request).execute();
                InputStream inputStream = response.body() != null ? response.body().byteStream() : null;
                if (inputStream == null)
                    break;
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                byte[] bytes = new byte[BUFFER_SIZE];
                int len;
                while ((len = inputStream.read(bytes)) != -1) {
                    fileOutputStream.write(bytes, 0, len);
                }
                fileOutputStream.flush();
                fileOutputStream.close();
                inputStream.close();
                response.body().close();
                flag = true;
            } catch (Exception e) {
                CJLogger.e("quickDownload error:" + e.toString());
            }


        } while (false);
        return flag;
    }

    // 获取内容长度
    public long getContentLength(String downloadUrl) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(downloadUrl).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                long contentLength = 0;
                if (response.body() != null) {
                    contentLength = response.body().contentLength();
                }
                if (response.body() != null) {
                    response.body().close();
                }
                return contentLength;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    public String getInterntFileSize(String downloadUrl){
        long apkSize    = getContentLength(downloadUrl);
        return CJFile.getFileSieze(apkSize);
    }


    public void download(CJHttpDownloadInfo downloadInfo, CJHttpDownloadListner listener) {
        CJLogger.d("download:" + downloadInfo.url);
        downloadInfo.downloadSize = 0;
        File file = new File(downloadInfo.savePath);
        if (file.exists()) {
            if (downloadInfo.isOverwrite) {
                file.delete();
            } else {
                return;
            }
        }
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            CJLogger.d("download start...");
            long totalSize = getContentLength(downloadInfo.url);
            if (totalSize == 0) {
                if (listener != null) listener.onFailed(downloadInfo, CJHttpError.GET_LENGTH_ERROR);
                return;
            }
            downloadInfo.totalSize = totalSize;

            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(downloadInfo.url).build();
            Response response = client.newCall(request).execute();
            inputStream = response.body() != null ? response.body().byteStream() : null;
            if (inputStream == null) {
                if (listener != null) listener.onFailed(downloadInfo, CJHttpError.GET_CONTENT_ERROR);
                return;
            }
            fileOutputStream = new FileOutputStream(file);
            long lastTime = System.currentTimeMillis();
            long nowTime;
            byte[] bytes = new byte[BUFFER_SIZE];
            int len;
            while ((len = inputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, len);
                downloadInfo.downloadSize += len;
                nowTime = System.currentTimeMillis();
                if (nowTime - lastTime >= 200) {
                    lastTime = nowTime;
                    if (listener != null) listener.onProgress(downloadInfo);
                }
            }
            fileOutputStream.flush();
            if (listener != null) listener.onSuccess(downloadInfo);
        } catch (Exception e) {
            CJLogger.e("download error:" + e.toString());
            if (listener != null) listener.onFailed(downloadInfo, CJHttpError.UNKNOWN);
        } finally {
            try {
                if (inputStream != null)
                    inputStream.close();
                if (fileOutputStream != null)
                    fileOutputStream.close();
            } catch (Exception e) {
                CJLogger.e("download close error:" + e.toString());
            }
        }
    }

    // 获取网络类型
    public static int getNetworkType(Context context) {
        int strNetworkType = 0;
        NetworkInfo networkInfo = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                strNetworkType = 100;
            } else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                String _strSubTypeName = networkInfo.getSubtypeName();
                // TD-SCDMA networkType is 17
                int networkType = networkInfo.getSubtype();
                switch (networkType) {
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN: // api<8 : replace
                        // by
                        // 11
                        strNetworkType = 2;
                        break;
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B: // api<9 :
                        // replace by
                        // 14
                    case TelephonyManager.NETWORK_TYPE_EHRPD: // api<11 :
                        // replace by
                        // 12
                    case TelephonyManager.NETWORK_TYPE_HSPAP: // api<13 :
                        // replace by
                        // 15
                        strNetworkType = 3;
                        break;
                    case TelephonyManager.NETWORK_TYPE_LTE: // api<11 : replace
                        // by
                        // 13
                        strNetworkType = 4;
                        break;
                    default:
                        if (_strSubTypeName.equalsIgnoreCase("TD-SCDMA") || _strSubTypeName.equalsIgnoreCase("WCDMA") || _strSubTypeName.equalsIgnoreCase("CDMA2000")) {
                            strNetworkType = 3;
                        } else {
                            strNetworkType = 0;
                        }
                        break;
                }
            }
        }
        return strNetworkType;
    }
}
